/*
 * drv_uart.c
 *
 *  Created on: Jul 12, 2021
 *      Author: dbw
 */

#include "drv_uart.h"
#include <string.h>

extern UART_HandleTypeDef huart1;

uart_t uart1 = { .handle = &huart1, };

void drv_uart_init(void)
{

}

void drv_uart_set_callback(uart_t *uart, uart_rx_cb_t rx_cb)
{
    uart->rx_cb = rx_cb;
}

void drv_uart_send_byte(uart_t *uart, uint8_t data)
{
    __HAL_UART_CLEAR_FLAG(uart->handle, UART_FLAG_TC);

    uart->handle->Instance->DR = data;
    while (__HAL_UART_GET_FLAG(uart->handle, UART_FLAG_TC) == RESET);
}

void drv_uart_send(uart_t *uart, const void *buf, int len)
{
    for (int i = 0; i < len; i++)
    {
        drv_uart_send_byte(uart, ((const uint8_t*) buf)[i]);
    }

}

void drv_uart_send_str(uart_t *uart, const char *str)
{
    drv_uart_send(uart, str, strlen(str));
}

static void notify_rx(uart_t *uart)
{
    if (uart->rx_index && uart->rx_cb)
    {
        uart->rx_cb(uart, uart->rx_buf, uart->rx_index);
    }
    uart->rx_index = 0;
}

static void uart_isr(uart_t *uart)
{
    if ((__HAL_UART_GET_FLAG(uart->handle, UART_FLAG_RXNE) != RESET)
            && (__HAL_UART_GET_IT_SOURCE(uart->handle, UART_IT_RXNE) != RESET))
    {
        uint8_t ch = uart->handle->Instance->DR & 0xff;

        uart->rx_buf[uart->rx_index++] = ch;
        if (uart->rx_index >= sizeof(uart->rx_buf))
        {
            notify_rx(uart);
        }

    }
    else if ((__HAL_UART_GET_FLAG(uart->handle, UART_FLAG_IDLE) != RESET)
            && (__HAL_UART_GET_IT_SOURCE(uart->handle, UART_IT_IDLE) != RESET))
    {
        notify_rx(uart);
        __HAL_UART_CLEAR_IDLEFLAG(uart->handle);
    }
    else
    {
        __HAL_UART_CLEAR_FLAG(uart->handle, uart->handle->Instance->SR);
        __HAL_UART_CLEAR_PEFLAG(uart->handle);
    }
}

void USART1_IRQHandler(void)
{
    uart_isr(&uart1);
}
